package com.example.nio.security.custom;

import cn.hutool.json.JSONUtil;
import com.example.nio.config.RedisConfig;
import com.example.nio.security.dmo.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.log.LogMessage;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@Component
public class MyAnonymousAuthenticationFilter extends GenericFilterBean {

    @Autowired
    private RedisConfig redisConfig;

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        if (SecurityContextHolder.getContext().getAuthentication() == null) {
            String authorization = ((HttpServletRequest) req).getHeader("authorization");
            String token = redisConfig.getStringBySer(authorization);
            if (token != null && !"".equals(token)){
                SysUser user = JSONUtil.toBean(token, SysUser.class);
                SecurityContextHolder.setContext(
                        new SecurityContextImpl(
                                new Authentication() {
                                    @Override
                                    public Collection<? extends GrantedAuthority> getAuthorities() {
                                        ArrayList<GrantedAuthority> list = new ArrayList<>();
                                        for (String role:user.getRoles()){
                                            list.add(new SimpleGrantedAuthority("ROLE_" + role));
                                        }
                                        return list;
                                    }
                                    @Override
                                    public Object getCredentials() {
                                        return user.getPassword();
                                    }
                                    @Override
                                    public Object getDetails() {
                                        return user;
                                    }
                                    @Override
                                    public Object getPrincipal() {
                                        return user;
                                    }
                                    @Override
                                    public boolean isAuthenticated() {
                                        return true;
                                    }
                                    @Override
                                    public void setAuthenticated(boolean b) throws IllegalArgumentException {
                                    }
                                    @Override
                                    public String getName() {
                                        return user.getUsername();
                                    }
                                }
                        )
                );
            }
            if (this.logger.isTraceEnabled()) {
                this.logger.trace(LogMessage.of(() -> {
                    return "Set SecurityContextHolder to " + SecurityContextHolder.getContext().getAuthentication();
                }));
            } else {
                this.logger.debug("Set SecurityContextHolder to anonymous SecurityContext");
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace(LogMessage.of(() -> {
                return "Did not set SecurityContextHolder since already authenticated " + SecurityContextHolder.getContext().getAuthentication();
            }));
        }

        chain.doFilter(req, res);
    }
}
